﻿using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;

namespace UnitTestProject1
{
    public class EntityHelper
    {
        // 去下划线,转大写  
        public static string ToSplitFirstUpper(string file)
        {
            string[] words = file.Split('_');
            StringBuilder firstUpperWorld = new StringBuilder();
            foreach (string word in words)
            {
                string firstUpper = ToFirstUpper(word);
                firstUpperWorld.Append(firstUpper);
            }
            string firstUpperFile = firstUpperWorld.ToString().TrimEnd(new char[] { '_' });
            return firstUpperFile;
        }

        // 将字符串设置成首字母大写  
        public static string ToFirstUpper(string field)
        {
            string first = field.Substring(0, 1).ToUpperInvariant();
            string result = first;
            if (field.Length > 1)
            {
                string after = field.Substring(1).ToLower();
                result = first + after;
            }
            return result;
        }

        public static List<Entity> GetEntities(string connectionString, List<string> databases)
        {
            var list = new List<Entity>();
            var conn = new MySqlConnection(connectionString);
            try
            {
                conn.Open();
                var dbs = string.Join("','", databases.ToArray());
                var cmd = string.Format(@"SELECT `information_schema`.`COLUMNS`.`TABLE_SCHEMA`
                                                    ,`information_schema`.`COLUMNS`.`TABLE_NAME`
                                                    ,`information_schema`.`COLUMNS`.`COLUMN_NAME`
                                                    ,`information_schema`.`COLUMNS`.`DATA_TYPE`
                                                    ,`information_schema`.`COLUMNS`.`COLUMN_COMMENT`,IS_NULLABLE
                                                FROM `information_schema`.`COLUMNS`
                                                WHERE `information_schema`.`COLUMNS`.`TABLE_SCHEMA` IN ('{0}') ", dbs);
                using (var reader = MySqlHelper.ExecuteReader(conn, cmd))
                {
                    while (reader.Read())
                    {
                        var db = reader["TABLE_SCHEMA"].ToString();
                        var table = reader["TABLE_NAME"].ToString();
                        var column = reader["COLUMN_NAME"].ToString();
                        var type = reader["DATA_TYPE"].ToString();
                        var comment = reader["COLUMN_COMMENT"].ToString();
                        var isnull = reader["IS_NULLABLE"].ToString() == "YES";
                        var entity = list.FirstOrDefault(x => x.EntityName == table);
                        var field = new Field
                        {
                            Name = column,
                            Type = GetCLRType(type, isnull),
                            Comment = comment
                        };

                        if (entity == null)
                        {
                            entity = new Entity(table);
                            entity.Fields.Add(field);

                            list.Add(entity);
                        }
                        else
                        {
                            entity.Fields.Add(field);
                        }
                    }
                }
            }
            finally
            {
                conn.Close();
            }

            return list;
        }

        public static string GetCLRType(string dbType, bool isnull)
        {
            switch (dbType)
            {
                case "tinyint":
                case "smallint":
                case "mediumint":
                case "int":
                case "integer":
                    if (isnull)
                    {
                        return "int?";
                    }
                    return "int";
                case "bigint":
                    if (isnull)
                    {
                        return "long?";
                    }
                    else
                    {

                        return "long";
                    }
                case "double":
                    if (isnull)
                    {
                        return "double?";
                    }
                    else
                    {

                        return "double";
                    }
                case "float":
                    if (isnull)
                    {
                        return "float?";
                    }
                    else
                    {

                        return "float";
                    }
                case "decimal":
                    if (isnull)
                    {
                        return "decimal?";
                    }
                    else
                    {

                        return "decimal";
                    }
                case "numeric":
                case "real":
                    if (isnull)
                    {
                        return "decimal?";
                    }
                    else
                    {

                        return "decimal";
                    }
                case "bit":
                    if (isnull)
                    {
                        return "bool?";
                    }
                    else
                    {

                        return "bool";
                    }
                case "date":
                case "time":
                case "year":
                case "datetime":
                case "timestamp":
                    if (isnull)
                    {
                        return "DateTime?";
                    }
                    else
                    {

                        return "DateTime";
                    }
                case "tinyblob":
                case "blob":
                case "mediumblob":
                case "longblog":
                case "binary":
                case "varbinary":
                    return "byte[]";
                case "char":
                case "varchar":
                case "tinytext":
                case "text":
                case "mediumtext":
                case "longtext":
                    return "string";
                case "point":
                case "linestring":
                case "polygon":
                case "geometry":
                case "multipoint":
                case "multilinestring":
                case "multipolygon":
                case "geometrycollection":
                case "enum":
                case "set":
                default:
                    return dbType;
            }
        }
    }

    public class Entity
    {
        public Entity()
        {
            this.Fields = new List<Field>();
        }

        public Entity(string name)
            : this()
        {
            this.EntityName = name;
        }

        public string EntityName { get; set; }
        public List<Field> Fields { get; set; }
    }

    public class Field
    {
        public string Name { get; set; }
        public string Type { get; set; }
        public string Comment { get; set; }
    }
}
